package pl.enigmatic.random;

public class RandomNumber<N extends Number> extends Random<N> {

	private final Cast<?> getCast(final Class<? extends Number> clazz) {
		if (clazz.equals(Byte.class)) {
			return new Cast<Byte>() {

				@Override
				public Byte cast(final Number number) {
					return number.byteValue();
				}
			};
		} else if (clazz.equals(Short.class)) {
			return new Cast<Short>() {

				@Override
				public Short cast(final Number number) {
					return number.shortValue();
				}
			};
		} else if (clazz.equals(Integer.class)) {
			return new Cast<Integer>() {

				@Override
				public Integer cast(final Number number) {
					return number.intValue();
				}
			};
		} else if (clazz.equals(Long.class)) {
			return new Cast<Long>() {

				@Override
				public Long cast(final Number number) {
					return number.longValue();
				}
			};
		} else if (clazz.equals(Float.class)) {
			return new Cast<Float>() {

				@Override
				public Float cast(final Number number) {
					return number.floatValue();
				}
			};
		} else {
			return new Cast<Double>() {

				@Override
				public Double cast(final Number number) {
					return number.doubleValue();
				}
			};
		}
	}

	private final N min;
	private final N max;
	private final Cast<N> cast;

	@SuppressWarnings("unchecked")
	public RandomNumber(final N min, final N max) {
		this.min = min;
		this.max = max;
		this.cast = (Cast<N>) getCast(min.getClass());
	}

	@Override
	public N getRandomValue() {
		return cast.cast(getDouble(min.doubleValue(), max.doubleValue()));
	}

	/**
	 * @return the min
	 */
	public N getMin() {
		return min;
	}

	/**
	 * @return the max
	 */
	public N getMax() {
		return max;
	}

	private interface Cast<N> {

		public N cast(Number number);
	}
}
